﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Wisdom.Core
{
    public class BuildManager : IBuildManager
    {
        protected IEnumerable<Assembly> referencedAssemblies;
        protected IEnumerable<Type> publicTypes;
        protected IEnumerable<Type> concreteTypes;

        /// <summary>
        /// Gets the assemblies.
        /// </summary>
        /// <value>The assemblies.</value>
        public virtual IEnumerable<Assembly> Assemblies
        {
            get
            {
                if (referencedAssemblies == null)
                {
                    if (Assembly.GetEntryAssembly() != null)
                    {
                        referencedAssemblies = Assembly.GetExecutingAssembly()
                                                       .GetReferencedAssemblies()
                                                       .Select(Assembly.Load)
                                                       .Where(assembly => !assembly.GlobalAssemblyCache)
                                                       .ToList();
                    }
                    else
                    {
                        referencedAssemblies = System.Web.Compilation.BuildManager.GetReferencedAssemblies()
                                                     .Cast<Assembly>()
                                                     .Where(assembly => !assembly.GlobalAssemblyCache)
                                                     .ToList();
                    }
                }
                return referencedAssemblies;
            }
        }

        /// <summary>
        /// Gets the available public types of <see cref="Assemblies"/>.
        /// </summary>
        /// <value>The concrete types.</value>
        public IEnumerable<Type> PublicTypes
        {
            get
            {
                return publicTypes ?? (publicTypes = Assemblies.PublicTypes().ToList());
            }
        }

        /// <summary>
        /// Gets the available concrete types of <see cref="Assemblies"/>.
        /// </summary>
        /// <value>The concrete types.</value>
        public IEnumerable<Type> ConcreteTypes
        {
            get
            {
                return concreteTypes ?? (concreteTypes = Assemblies.ConcreteTypes().ToList());
            }
        }
    }
}